import { EntityManager, MikroORM } from '@mikro-orm/mysql';
import { InjectEntityManager, InjectMikroORM } from '@mikro-orm/nestjs';
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { PersonalAccessTokens } from "@entities/PersonalAccessTokens";
import CryptoJS from 'crypto-js';
import { Users } from "@entities/Users";
import { wrap } from '@mikro-orm/core';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    @InjectMikroORM('zp')
    private readonly orm: MikroORM,
    @InjectEntityManager('zp')
    private readonly em: EntityManager
  ) { }

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {

    const orm = this.orm
    const knex = this.em.getKnex();
    const qb = this.em.qb

    const request = context.switchToHttp().getRequest() as Request

    const token = request.headers['token']

    if (!!token) {
      return new Promise(async (resolve, inject) => {
        // const parts = token.split('|')
        // const key = CryptoJS.SHA256(parts[1]).toString()
        // const tokenModel = await this.em.getRepository(PersonalAccessTokens).findOne({ 'token': key })
        // const user_id = tokenModel.tokenableId
        // const userModel = await this.em.getRepository(Users).findOne({ 'id': user_id })

        const userObject = await this.validateToken(token) //wrap(userModel).toObject()

        if (userObject) {
          request['user'] = userObject
          resolve(true)
        }
        else
          resolve(false)
      })
    }

    return false
  }

  async validateToken(token) {
    const parts = token.split('|')
    const key = CryptoJS.SHA256(parts[1]).toString()
    //const key = parts[1]
    const tokenModel = await this.em.getRepository(PersonalAccessTokens).findOne({ 'token': key })
    const user_id = tokenModel.tokenableId
    const userModel = await this.em.getRepository(Users).findOne({ 'id': user_id })
    const userObject = wrap(userModel).toObject()

    return userObject
  }
}
